package com.zxjbyte.yiyi.module.plugin.sse.processor;

import com.zxjbyte.yiyi.module.plugin.sse.session.SseSession;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

/**
 * 回调处理类
 *
 * @Author zhangxingjia
 * @Date 2024/7/13 19:30
 * @Version: 1.0
 */
@Slf4j
public class SseEmitterCallBackProcessor {

    private final SseEmitter emitter;
    private final String clientId;
    private final String userId;


    public static void createCallBack(final SseEmitter emitter, final String clientId, final String userId) {
        new SseEmitterCallBackProcessor(emitter, clientId, userId);
    }

    public SseEmitterCallBackProcessor(final SseEmitter emitter, final String clientId, final String userId){
        this.emitter = emitter;
        this.clientId = clientId;
        this.userId = userId;
        setupCallbacks();
    }

    private void setupCallbacks() {
        emitter.onCompletion(this::handleCompletion);
        emitter.onTimeout(this::handleTimeout);
        emitter.onError(this::handleError);
    }

    /**
     * 当 SseEmitter 的连接正常结束时（即服务器主动调用 emitter.complete() 或者客户端关闭连接），会触发 onCompletion 回调。
     */
    private void handleCompletion() {
        log.info("SSE connection completed for client:{}, userId:{}", clientId, userId);
        SseSession.removeConnection(clientId, userId);
    }

    /**
     *当 SseEmitter 设置的超时时间到达且没有发送任何事件时，会触发 onTimeout 回调。
     * 可以通过 emitter.setTimeout(long timeout) 方法设置超时时间。
     */
    private void handleTimeout() {
        log.info("SSE connection timed out for client:{}, userId:{}", clientId, userId);
        SseSession.removeConnection(clientId, userId);
    }

    /**
     * 当 SseEmitter 在尝试发送事件时发生异常，会触发 onError 回调。异常可能由网络问题、客户端断开连接或者其他 I/O 错误引起。
     * @param t
     */
    private void handleError(Throwable t) {
        log.info("SSE connection error for client:{}, userId:{}, error: {}", clientId, userId, t.getMessage());
        SseSession.removeConnection(clientId, userId);
    }
}
